package com.fand.platform.configuration.service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.val;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;

import com.fand.dto.PaginationDto;
import com.fand.platform.configuration.dao.SiteDao;
import com.fand.platform.configuration.dto.DomainNaDto;
import com.fand.platform.configuration.dto.SiteDeDto;
import com.fand.platform.configuration.dto.SiteDto;

/**
 * 站服务
 * 
 * @author yaoHT
 * 
 */
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class SiteDefaultService implements SiteService {
	private SiteDao siteDao;

	@Override
	@Transactional
	public int deleteDomainNaBy1(DomainNaDto deleteDomainNa) {
		return this.siteDao.deleteDomainNaBy1(deleteDomainNa, new String[] {});
	}

	@Override
	@Transactional
	public int deleteDomainNaByIds(DomainNaDto deleteDomainNa) {
		return this.siteDao.deleteDomainNaByIds(deleteDomainNa);
	}

	@Override
	@Transactional
	public int deleteSiteBy1(SiteDto deleteSite) {
		return this.siteDao.deleteSiteBy1(deleteSite, new String[] {});
	}

	@Override
	@Transactional
	public int deleteSiteByIds(SiteDto deleteSite) {
		return this.siteDao.deleteSiteByIds(deleteSite);
	}

	@Override
	public List<DomainNaDto> findDomainNaBy1(DomainNaDto findDomainNa) {
		return this.siteDao.selectDomainNaBy1ForMappedObjectList(DomainNaDto.class, findDomainNa, new String[] {},
				new String[] {});
	}

	@Override
	public List<DomainNaDto> findDomainNaBy2(DomainNaDto findDomainNa) {
		return this.siteDao.selectDomainNaBy2ForMappedObjectList(DomainNaDto.class, findDomainNa);
	}

	@Override
	public List<SiteDto> findSite() {
		return this.siteDao.selectSiteForMappedObjectList(SiteDto.class);
	}

	@Override
	public List<SiteDto> findSiteBy1(SiteDto findSite) {
		return this.siteDao.selectSiteBy1ForMappedObjectList(SiteDto.class, findSite, new String[] {},
				new String[] {});
	}

	@Override
	public DomainNaDto getDomainNaBy1(DomainNaDto getDomainNa) {
		return this.siteDao.selectDomainNaBy1ForMappedObject(DomainNaDto.class, getDomainNa, new String[] {},
				new String[] {});
	}

	@Override
	public DomainNaDto getDomainNaById(DomainNaDto getDomainNa) {
		return this.siteDao.selectDomainNaByIdForMappedObject(DomainNaDto.class, getDomainNa);
	}

	@Override
	public SiteDto getSiteBy1(SiteDto getSite) {
		return this.siteDao.selectSiteBy1ForMappedObject(SiteDto.class, getSite, null, "id");
	}

	@Override
	@Cacheable(value = SiteService.CACHE_NAME)
	public SiteDto getSiteByDefault() {
		return this.siteDao.selectSiteByDefaultForMappedObject(SiteDto.class);
	}

	@Override
	@Cacheable(value = SiteService.CACHE_NAME)
	public SiteDto getSiteByDomainUrl(String domainUrl) {
		return this.siteDao.selectSiteByDomainUrlForMappedObject(SiteDto.class, domainUrl);
	}

	@Override
	public SiteDto getSiteById(SiteDto getSite) {
		return this.siteDao.selectSiteByIdForMappedObject(SiteDto.class, getSite);
	}

	@Override
	public PaginationDto<DomainNaDto> paginationDomainNaBy1ForDomainNaList(DomainNaDto paginationDomainNa) {
		return this.siteDao.paginationDomainNaBy1ForMappedObjectList(DomainNaDto.class, paginationDomainNa);
	}

	@Override
	public PaginationDto<Map<String, Object>> paginationDomainNaBy1ForMapList(DomainNaDto paginationDomainNa) {
		return this.siteDao.paginationDomainNaBy1ForMapList(paginationDomainNa);
	}

	@Override
	public PaginationDto<Map<String, Object>> paginationSiteBy1ForMapList(SiteDto paginationSite) {
		return this.siteDao.paginationSiteBy1ForMapList(paginationSite);
	}

	@Override
	public PaginationDto<SiteDto> paginationSiteBy1ForSiteList(SiteDto paginationSite) {
		return this.siteDao.paginationSiteBy1ForMappedObjectList(SiteDto.class, paginationSite);
	}

	@Override
	public Integer readDomainNaBy2ForInteger(DomainNaDto readDomainNa) {
		return this.siteDao.selectDomainNaBy2ForObject(Integer.class, readDomainNa, null);
	}

	@Override
	public Integer readDomainNaByCodeNqIdForInteger(DomainNaDto readDomainNa) {
		return this.siteDao.selectDomainNaByCodeNqIdForInteger(readDomainNa);
	}

	@Override
	public List<Integer> readListDomainNaBy1(DomainNaDto readDomainNa) {
		return this.siteDao.selectDomainNaBy1ForObjectList(Integer.class, readDomainNa, null, new String[] {});
	}

	@Override
	public List<Integer> readListDomainNaBy2(DomainNaDto readDomainNa) {
		return this.siteDao.selectDomainNaBy2ForObjectList(Integer.class, readDomainNa, null);
	}

	@Override
	public List<Integer> readListSiteBy1(SiteDto readSite) {
		return this.siteDao.selectSiteBy1ForObjectList(Integer.class, readSite, null, new String[] {});
	}

	@Override
	public List<Integer> readListSiteBy2(SiteDto readSite) {
		return this.siteDao.selectSiteBy2ForObjectList(Integer.class, readSite, null);
	}

	@Override
	public Integer readSiteBy2ForInteger(SiteDto readSite) {
		return this.siteDao.selectSiteBy2ForObject(Integer.class, readSite, null);
	}

	@Override
	public Integer readSiteByCodeNqIdForInteger(SiteDto readSite) {
		return this.siteDao.selectSiteByCodeNqIdForInteger(readSite);
	}

	@Override
	@CacheEvict(value = SiteService.CACHE_NAME, allEntries = true)
	public void reload() {
	}

	@Override
	@Transactional
	public DomainNaDto saveDomainNaBy2ForDomainNa(DomainNaDto saveDomainNa) {
		DomainNaDto oldDomainNa = this.siteDao.selectDomainNaBy1ForMappedObject(DomainNaDto.class, saveDomainNa,
				new String[] {}, new String[] {});

		if (oldDomainNa == null) {
			this.siteDao.insertDomainNaBy1(saveDomainNa, new String[] {});

			return saveDomainNa;
		}

		String[] updateProperties = com.fand.utils.BeanUtils.differProperties(saveDomainNa, oldDomainNa);

		if (ArrayUtils.isNotEmpty(updateProperties)) {
			this.siteDao.updateDomainNaBy1(saveDomainNa, updateProperties, new String[] {});
		}

		return saveDomainNa;
	}

	@Override
	@Transactional
	public DomainNaDto saveDomainNaByIdOrCodeForDomainNa(DomainNaDto saveDomainNa) {
		String[] whereEqProperties;

		if (StringUtils.isNotBlank(saveDomainNa.getId())) {
			whereEqProperties = new String[] { "id" };
		} else {
			whereEqProperties = new String[] { "code" };
		}

		DomainNaDto oldDomainNa = this.siteDao.selectDomainNaBy1ForMappedObject(DomainNaDto.class, saveDomainNa,
				null, whereEqProperties);

		if (oldDomainNa == null) {
			saveDomainNa.setId(UUID.randomUUID().toString());
			saveDomainNa.setBeginDaTi(new Date());
			saveDomainNa.setEndDaTi(new DateTime(9999, 12, 31, 0, 0, 0, 0).toDate());

			this.siteDao.insertDomainNaBy1(saveDomainNa);

			return saveDomainNa;
		}

		String[] updateProperties = com.fand.utils.BeanUtils.differProperties(saveDomainNa, oldDomainNa, "siteId",
				"code", "name", "orderNum");

		if (ArrayUtils.isNotEmpty(updateProperties)) {
			this.siteDao.updateDomainNaBy1(saveDomainNa, updateProperties, whereEqProperties);

			com.fand.utils.BeanUtils.copyProperties(saveDomainNa, oldDomainNa, updateProperties);
		}

		return saveDomainNa;
	}

	@Override
	@Transactional
	public SiteDto saveSiteBy2ForSite(SiteDto saveSite) {
		SiteDto oldSite = this.siteDao.selectSiteBy1ForMappedObject(SiteDto.class, saveSite, new String[] {},
				new String[] {});

		if (oldSite == null) {
			this.siteDao.insertSiteBy1(saveSite, new String[] {});

			return saveSite;
		}

		String[] updateProperties = com.fand.utils.BeanUtils.differProperties(saveSite, oldSite);

		if (ArrayUtils.isNotEmpty(updateProperties)) {
			this.siteDao.updateSiteBy1(saveSite, updateProperties, new String[] {});

			com.fand.utils.BeanUtils.copyProperties(saveSite, oldSite, updateProperties);
		}

		return oldSite;
	}

	@Override
	@Transactional
	public SiteDto saveSiteByIdOrCodeForSite(SiteDto saveSite) {
		String[] whereEqProperties;

		if (StringUtils.isNotBlank(saveSite.getId())) {
			whereEqProperties = new String[] { "id" };
		} else {
			whereEqProperties = new String[] { "code" };
		}

		SiteDto oldSite = this.siteDao
				.selectSiteBy1ForMappedObject(SiteDto.class, saveSite, null, whereEqProperties);

		final boolean isDefault = BooleanUtils.toBoolean(saveSite.getDefaultCo());

		if (oldSite == null) {
			saveSite.setId(UUID.randomUUID().toString());
			saveSite.setBeginDaTi(new Date());
			saveSite.setEndDaTi(new DateTime(9999, 12, 31, 0, 0, 0, 0).toDate());

			this.siteDao.insertSiteBy1(saveSite);

			if (isDefault) {
				this.saveSiteDeByEntityId(saveSite.getId());
			}

			return saveSite;
		}

		String[] updateProperties = com.fand.utils.BeanUtils.differProperties(saveSite, oldSite, "code", "name");

		if (ArrayUtils.isNotEmpty(updateProperties)) {
			this.siteDao.updateSiteBy1(saveSite, updateProperties, whereEqProperties);

			com.fand.utils.BeanUtils.copyProperties(saveSite, oldSite, updateProperties);
		}

		if (isDefault) {
			this.saveSiteDeByEntityId(oldSite.getId());
		}

		return oldSite;
	}

	private int saveSiteDeByEntityId(String entityId) {
		int rowCount = 0;

		val selectSiteDe = new SiteDeDto();

		selectSiteDe.setEntityId(entityId);

		int count = this.siteDao.selectSiteDeBy1ForObject(Integer.class, selectSiteDe, null, "entityId");

		if (count > 0) {
			return rowCount;
		}

		rowCount += this.siteDao.deleteSiteDeByNotEntityId(entityId);

		selectSiteDe.setId(UUID.randomUUID().toString());
		selectSiteDe.setBeginDaTi(new Date());
		selectSiteDe.setEndDaTi(new DateTime(9999, 12, 31, 0, 0, 0, 0).toDate());

		rowCount += this.siteDao.insertSiteDeBy1(selectSiteDe);

		return rowCount;
	}

	@Override
	@Transactional
	public int setDomainNaBy1(DomainNaDto setDomainNa) {
		return this.siteDao.updateDomainNaBy1(setDomainNa, new String[] {}, new String[] {});
	}

	@Override
	@Transactional
	public int setDomainNaBy2(DomainNaDto setDomainNa) {
		return this.siteDao.updateDomainNaBy2(setDomainNa);
	}

	@Override
	@Transactional
	public int setSiteBy1(SiteDto setSite) {
		return this.siteDao.updateSiteBy1(setSite, new String[] {}, new String[] {});
	}

	@Override
	@Transactional
	public int setSiteBy2(SiteDto setSite) {
		return this.siteDao.updateSiteBy2(setSite);
	}
}